home *** CD-ROM | disk | FTP | other *** search
- From: jik@pit-manager.MIT.EDU (Jonathan I. Kamens)
- Newsgroups: comp.sources.misc
- Subject: v17i024: delete - MIT Athena delete/undelete programs, Part02/04
- Message-ID: <1991Feb25.180718.4331@sparky.IMD.Sterling.COM>
- Date: 25 Feb 91 18:07:18 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 88688dcf 2e89e597 83bae5e1 a0bf0fe3
-
- Submitted-by: Jonathan I. Kamens <jik@pit-manager.MIT.EDU>
- Posting-number: Volume 17, Issue 24
- Archive-name: delete/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 4)."
- # Contents: Makefile expunge.c lsdel.c undelete.c util.c
- # Wrapped by jik@pit-manager on Fri Feb 22 08:14:23 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(5485 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# Copyright 1988 Massachusetts Institute of Technology.
- X#
- X# For copying and distribution information, see the file
- X# "mit-copyright.h".
- X#
- X# $Source: /afs/athena.mit.edu/user/j/jik/delete/src/RCS/Makefile,v $
- X# $Author: jik $
- X# $Header: /afs/athena.mit.edu/user/j/jik/delete/src/RCS/Makefile,v 1.28 91/02/22 07:35:51 jik Exp $
- X#
- X
- XDESTDIR=
- XTARGETS= delete undelete expunge purge lsdel
- XINSTALLDIR= /usr/bin
- XMANDIR= /usr/man
- XMANSECT= 1
- XCC= cc
- XDEPEND= /usr/bin/X11/makedepend
- XCOMPILE_ET= compile_et
- XLINT= lint
- XDEFINES=
- X
- X
- X# These variables apply only if you want this program to recognize
- X# Andrew File System mount points. If you don't want to support AFS,
- X# then they should all be commented out or set to nothing.
- X#
- X# AFSINC is the include directory for AFS header files.
- X# AFSLIB is the library directory that contains the AFS libraries.
- X#
- X# AFSINC=
- X# AFSLIB=
- X# AFSINCS= -I$(AFSINC)
- X# AFSLDFLAGS= -L$(AFSLIB) -L$(AFSLIB)/afs
- X# AFSLIBS= -lsys -lrx -llwp $(AFSLIB)/afs/util.a
- X# AFSDEFINES= -DAFS_MOUNTPOINTS
- X
- X
- X# If you install the com_err library and include files in directories
- X# that your compiler and linker know how to find, you don't have to
- X# set these variables. Otherwise, you do.
- X#
- X# ETINCS is a -I flag pointing to the directory in which the et header
- X# files are stored.
- X# ETLDFLAGS is a -L flag pointing to the directory where the et
- X# library is stored.
- X#
- X# ETINCS=
- X# ETLDFLAGS=
- X
- X
- X# You probably won't have to edit anything below this line.
- X
- XETLIBS= -lcom_err
- XINCLUDES= $(ETINCS) $(AFSINCS)
- XLDFLAGS= $(ETLDFLAGS) $(AFSLDFLAGS)
- XLIBS= $(ETLIBS) $(AFSLIBS)
- XCDEBUGFLAGS= -O
- XCFLAGS= $(INCLUDES) $(DEFINES) $(AFSDEFINES) $(CDEBUGFLAGS)
- XLINTFLAGS= -u $(INCLUDES) $(DEFINES) $(AFSDEFINES) $(CDEBUGFLAGS)
- XLINTLIBS=
- X
- XSRCS= delete.c undelete.c directories.c pattern.c util.c\
- X expunge.c lsdel.c col.c shell_regexp.c\
- X errors.c stack.c
- XINCS= col.h delete.h directories.h expunge.h lsdel.h\
- X mit-copyright.h pattern.h undelete.h util.h\
- X shell_regexp.h errors.h stack.h
- XETS= delete_errs.h delete_errs.c
- XETSRCS= delete_errs.et
- X
- XMANS= man1/delete.1 man1/expunge.1 man1/lsdel.1 man1/purge.1\
- X man1/undelete.1
- X
- XARCHIVE= README Makefile PATCHLEVEL $(SRCS) $(INCS) $(MANS)\
- X $(ETSRCS)
- XARCHIVEDIRS= man1
- X
- XDELETEOBJS= delete.o util.o delete_errs.o errors.o
- XUNDELETEOBJS= undelete.o directories.o util.o pattern.o\
- X shell_regexp.o delete_errs.o errors.o stack.o
- XEXPUNGEOBJS= expunge.o directories.o pattern.o util.o col.o\
- X shell_regexp.o delete_errs.o errors.o stack.o
- XLSDELOBJS= lsdel.o util.o directories.o pattern.o col.o\
- X shell_regexp.o delete_errs.o errors.o stack.o
- X
- XDELETESRC= delete.c util.c delete_errs.c errors.c
- XUNDELETESRC= undelete.c directories.c util.c pattern.c\
- X shell_regexp.c delete_errs.c errors.c stack.c
- XEXPUNGESRC= expunge.c directories.c pattern.c util.c col.c\
- X shell_regexp.c delete_errs.c errors.c stack.c
- XLSDELSRC= lsdel.c util.c directories.c pattern.c col.c\
- X shell_regexp.c delete_errs.c errors.c stack.c
- X
- X.SUFFIXES: .c .h .et
- X
- X.et.h: $*.et
- X ${COMPILE_ET} $*.et
- X.et.c: $*.et
- X ${COMPILE_ET} $*.et
- X
- Xall: $(TARGETS)
- X
- Xlint_all: lint_delete lint_undelete lint_expunge lint_lsdel
- X
- Xinstall:: bin_install man_install
- X
- X# Errors are ignored on bin_install and man_install because make on
- X# some platforms, in combination with the shell, does really stupid
- X# things and detects an error where there is none.
- X
- Xman_install:
- X -for i in $(TARGETS) ; do\
- X install -c man1/$$i.1\
- X $(DESTDIR)$(MANDIR)/man$(MANSECT)/$$i.$(MANSECT);\
- X done
- X
- Xbin_install: $(TARGETS)
- X -for i in $(TARGETS) ; do\
- X if [ -f $(DESTDIR)$(INSTALLDIR)/$$i ]; then\
- X mv $(DESTDIR)$(INSTALLDIR)/$$i $(DESTDIR)$(INSTALLDIR)/.#$$i ; \
- X fi; \
- X install -c -s $$i $(DESTDIR)$(INSTALLDIR) ; \
- X done
- X
- Xdelete: $(DELETEOBJS)
- X $(CC) $(LDFLAGS) $(CFLAGS) -o delete $(DELETEOBJS) $(LIBS)
- X
- Xsaber_delete:
- X #setopt program_name delete
- X #load $(LDFLAGS) $(CFLAGS) $(DELETESRC) $(LIBS)
- X
- Xlint_delete: $(DELETESRC)
- X $(LINT) $(LINTFLAGS) $(DELETESRC) $(LINTLIBS)
- X
- Xundelete: $(UNDELETEOBJS)
- X $(CC) $(LDFLAGS) $(CFLAGS) -o undelete $(UNDELETEOBJS) $(LIBS)
- X
- Xsaber_undelete:
- X #setopt program_name undelete
- X #load $(LDFLAGS) $(CFLAGS) $(UNDELETESRC) $(LIBS)
- X
- Xlint_undelete: $(UNDELETESRC)
- X $(LINT) $(LINTFLAGS) $(UNDELETESRC) $(LINTLIBS)
- X
- Xexpunge: $(EXPUNGEOBJS)
- X $(CC) $(LDFLAGS) $(CFLAGS) -o expunge $(EXPUNGEOBJS) $(LIBS)
- X
- Xsaber_expunge:
- X #setopt program_name expunge
- X #load $(LDFLAGS) $(CFLAGS) $(EXPUNGESRC) $(LIBS)
- X
- Xlint_expunge: $(EXPUNGESRC)
- X $(LINT) $(LINTFLAGS) $(EXPUNGESRC) $(LINTLIBS)
- X
- Xpurge: expunge
- X ln -s expunge purge
- X
- Xlsdel: $(LSDELOBJS)
- X $(CC) $(LDFLAGS) $(CFLAGS) -o lsdel $(LSDELOBJS) $(LIBS)
- X
- Xlint_lsdel: $(LSDELSRC)
- X $(LINT) $(LINTFLAGS) $(LSDELSRC) $(LINTLIBS)
- X
- Xsaber_lsdel:
- X #setopt program_name lsdel
- X #load $(LDFLAGS) $(CFLAGS) $(LSDELSRC) $(LIBS)
- X
- Xtar: $(ARCHIVE)
- X tar cvf - $(ARCHIVE) | compress > delete.tar.Z
- X
- Xshar: $(ARCHIVE)
- X makekit -oMANIFEST $(ARCHIVEDIRS) $(ARCHIVE)
- X
- Xpatch: $(ARCHIVE)
- X makepatch $(ARCHIVE)
- X mv patch delete.patch`cat PATCHLEVEL`
- X shar delete.patch`cat PATCHLEVEL` > delete.patch`cat PATCHLEVEL`.shar
- X
- Xclean::
- X -rm -f *~ *.bak *.o delete undelete lsdel expunge purge\
- X delete_errs.h delete_errs.c
- X
- Xdepend: $(SRCS) $(INCS) $(ETS)
- X $(DEPEND) -v $(CFLAGS) -s'# DO NOT DELETE' $(SRCS)
- X
- X$(DELETEOBJS): delete_errs.h
- X$(EXPUNGEOBJS): delete_errs.h
- X$(UNDELETEOBJS): delete_errs.h
- X$(LSDELOBJS): delete_errs.h
- X
- X# DO NOT DELETE THIS LINE -- makedepend depends on it
- END_OF_FILE
- if test 5485 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'expunge.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'expunge.c'\"
- else
- echo shar: Extracting \"'expunge.c'\" \(11287 characters\)
- sed "s/^X//" >'expunge.c' <<'END_OF_FILE'
- X/*
- X * $Source: /afs/athena.mit.edu/astaff/project/delete/src/RCS/expunge.c,v $
- X * $Author: jik $
- X *
- X * This program is part of a package including delete, undelete,
- X * lsdel, expunge and purge. The software suite is meant as a
- X * replacement for rm which allows for file recovery.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_expunge_c[] = "$Header: /afs/athena.mit.edu/astaff/project/delete/src/RCS/expunge.c,v 1.17 91/02/20 17:42:15 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/dir.h>
- X#include <sys/param.h>
- X#ifdef SYSV
- X#include <string.h>
- X#define index strchr
- X#define rindex strrchr
- X#else
- X#include <strings.h>
- X#endif /* SYSV */
- X#include <com_err.h>
- X#include <errno.h>
- X#include "col.h"
- X#include "util.h"
- X#include "directories.h"
- X#include "pattern.h"
- X#include "expunge.h"
- X#include "shell_regexp.h"
- X#include "mit-copyright.h"
- X#include "delete_errs.h"
- X#include "errors.h"
- X
- Xextern char *realloc();
- Xextern time_t current_time;
- Xextern int errno;
- X
- Xchar *whoami;
- X
- Xtime_t timev; /* minimum mod time before undeletion */
- X
- Xint interactive, /* query before each expunge */
- X recursive, /* expunge undeleted directories recursively */
- X noop, /* print what would be done instead of doing it */
- X verbose, /* print a line as each file is deleted */
- X force, /* do not ask for any confirmation */
- X listfiles, /* list files at toplevel */
- X yield, /* print yield of expunge at end */
- X f_links, /* follow symbolic links */
- X f_mounts; /* follow mount points */
- X
- Xint bytes_removed = 0;
- X
- X
- X
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X
- X initialize_del_error_table();
- X
- X whoami = lastpart(argv[0]);
- X if (*whoami == 'p') { /* we're doing a purge */
- X if (argc > 1) {
- X set_error(PURGE_TOO_MANY_ARGS);
- X error("");
- X exit(1);
- X }
- X if (purge())
- X error("purge");
- X exit(error_occurred ? 1 : 0);
- X }
- X timev = 0;
- X yield = interactive = recursive = noop = verbose = listfiles = force = 0;
- X while ((arg = getopt(argc, argv, "t:irfnvlysm")) != EOF) {
- X switch (arg) {
- X case 't':
- X timev = atoi(optarg);
- X break;
- X case 'i':
- X interactive++;
- X break;
- X case 'r':
- X recursive++;
- X break;
- X case 'f':
- X force++;
- X break;
- X case 'n':
- X noop++;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'l':
- X listfiles++;
- X break;
- X case 'y':
- X yield++;
- X break;
- X case 's':
- X f_links++;
- X break;
- X case 'm':
- X f_mounts++;
- X break;
- X default:
- X usage();
- X exit(1);
- X }
- X }
- X report_errors = ! force;
- X
- X if (optind == argc) {
- X char *dir;
- X dir = "."; /* current working directory */
- X if (expunge(&dir, 1))
- X error("expunging .");
- X }
- X else if (expunge(&argv[optind], argc - optind))
- X error("expunge");
- X
- X exit((error_occurred && (! force)) ? 1 : 0);
- X}
- X
- X
- X
- X
- X
- Xpurge()
- X{
- X char *home;
- X int retval;
- X
- X home = Malloc((unsigned) MAXPATHLEN);
- X if (! home) {
- X set_error(errno);
- X error("purge");
- X return error_code;
- X }
- X timev = interactive = noop = verbose = force = 0;
- X yield = listfiles = recursive = 1;
- X if (retval = get_home(home)) {
- X error("purge");
- X return retval;
- X }
- X
- X printf("Please be patient.... this may take a while.\n\n");
- X
- X if (retval = expunge(&home, 1)) {
- X error("expunge");
- X return retval;
- X }
- X return 0;
- X}
- X
- X
- X
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: %s [ options ] [ filename [ ... ]]\n", whoami);
- X fprintf(stderr, "Options are:\n");
- X fprintf(stderr, " -r recursive\n");
- X fprintf(stderr, " -i interactive\n");
- X fprintf(stderr, " -f force\n");
- X fprintf(stderr, " -t n n-day-or-older expunge\n");
- X fprintf(stderr, " -n noop\n");
- X fprintf(stderr, " -v verbose\n");
- X fprintf(stderr, " -l list files before expunging\n");
- X fprintf(stderr, " -s follow symbolic links to directories\n");
- X fprintf(stderr, " -m follow mount points\n");
- X fprintf(stderr, " -y print yield of expunge\n");
- X fprintf(stderr, " -- end options and start filenames\n");
- X}
- X
- X
- X
- X
- X
- Xint expunge(files, num)
- Xchar **files;
- Xint num;
- X{
- X char **found_files;
- X int num_found;
- X int status = 0;
- X int total = 0;
- X filerec *current;
- X int retval;
- X
- X if (initialize_tree())
- X exit(1);
- X
- X for ( ; num ; num--) {
- X retval = get_the_files(files[num - 1], &num_found, &found_files);
- X if (retval) {
- X error(files[num - 1]);
- X return retval;
- X }
- X
- X if (num_found) {
- X num_found = process_files(found_files, num_found);
- X if (num_found < 0) {
- X error("process_files");
- X return error_code;
- X }
- X }
- X
- X total += num_found;
- X if (! num_found) if (! force) {
- X /*
- X * There are three different situations here. Eiter we
- X * are dealing with an existing directory with no
- X * deleted files in it, or we are deleting with a
- X * non-existing deleted file with wildcards, or we are
- X * dealing with a non-existing deleted file without
- X * wildcards. In the former case we print nothing, and
- X * in the latter cases we print either "no match" or
- X * "not found" respectively
- X */
- X if (no_wildcards(files[num - 1])) {
- X if (! directory_exists(files[num - 1])) {
- X set_error(ENOENT);
- X error(files[num - 1]);
- X }
- X }
- X else {
- X set_error(ENOMATCH);
- X error(files[num - 1]);
- X }
- X }
- X }
- X if (total && listfiles) {
- X if (retval = list_files()) {
- X error("list_files");
- X return retval;
- X }
- X if (! force) if (! top_level()) {
- X set_status(EXPUNGE_NOT_EXPUNGED);
- X return error_code;
- X }
- X }
- X current = get_root_tree();
- X if (current) {
- X if (retval = expunge_specified(current)) {
- X error("expunge_specified");
- X status = retval;
- X }
- X }
- X current = get_cwd_tree();
- X if (current) {
- X if (retval = expunge_specified(current)) {
- X error("expunge_specified");
- X status = retval;
- X }
- X }
- X if (yield) {
- X if (noop)
- X printf("Total that would be expunged: %dk\n",
- X size_to_k(bytes_removed));
- X else
- X printf("Total expunged: %dk\n", size_to_k(bytes_removed));
- X }
- X return status;
- X}
- X
- X
- X
- Xexpunge_specified(leaf)
- Xfilerec *leaf;
- X{
- X int status = 0;
- X int do_it = 1;
- X int retval;
- X
- X if ((leaf->specified) && ((leaf->specs.st_mode & S_IFMT) == S_IFDIR)) {
- X char buf[MAXPATHLEN];
- X
- X if (retval = get_leaf_path(leaf, buf)) {
- X error("get_leaf_path");
- X return retval;
- X }
- X (void) convert_to_user_name(buf, buf);
- X
- X if (interactive) {
- X printf("%s: Expunge directory %s? ", whoami, buf);
- X status = (! (do_it = yes()));
- X }
- X }
- X if (do_it) {
- X if (leaf->dirs) {
- X if (retval = expunge_specified(leaf->dirs)) {
- X error("expunge_specified");
- X status = retval;
- X }
- X }
- X if (leaf->files) {
- X if (retval = expunge_specified(leaf->files)) {
- X error("expunge_specified");
- X status = retval;
- X }
- X }
- X }
- X if (leaf->specified && (! status)) {
- X if (retval = really_do_expunge(leaf)) {
- X error("really_do_expunge");
- X status = retval;
- X }
- X }
- X if (leaf->next) {
- X if (retval = expunge_specified(leaf->next)) {
- X error("expunge_specified");
- X status = retval;
- X }
- X }
- X
- X free_leaf(leaf);
- X return status;
- X}
- X
- X
- Xprocess_files(files, num)
- Xchar **files;
- Xint num;
- X{
- X int i, skipped = 0;
- X filerec *leaf;
- X
- X for (i = 0; i < num; i++) {
- X if (add_path_to_tree(files[i], &leaf)) {
- X error("add_path_to_tree");
- X return -1;
- X }
- X free(files[i]);
- X if (! timed_out(leaf, current_time, timev)) {
- X free_leaf(leaf);
- X skipped++;
- X }
- X }
- X free((char *) files);
- X return(num-skipped);
- X}
- X
- X
- X
- X
- X
- X
- X
- X
- X
- Xreally_do_expunge(file_ent)
- Xfilerec *file_ent;
- X{
- X char real[MAXPATHLEN], user[MAXPATHLEN];
- X int status;
- X int retval;
- X
- X if (retval = get_leaf_path(file_ent, real)) {
- X error("get_leaf_path");
- X return retval;
- X }
- X (void) convert_to_user_name(real, user);
- X
- X if (interactive) {
- X printf ("%s: Expunge %s (%dk)? ", whoami, user,
- X size_to_k(file_ent->specs.st_size));
- X if (! yes()) {
- X set_status(EXPUNGE_NOT_EXPUNGED);
- X return error_code;
- X }
- X }
- X
- X if (noop) {
- X bytes_removed += file_ent->specs.st_size;
- X printf("%s: %s (%dk) would be expunged (%dk total)\n", whoami, user,
- X size_to_k(file_ent->specs.st_size),
- X size_to_k(bytes_removed));
- X return 0;
- X }
- X
- X if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
- X status = rmdir(real);
- X else
- X status = unlink(real);
- X if (! status) {
- X bytes_removed += file_ent->specs.st_size;
- X if (verbose)
- X printf("%s: %s (%dk) expunged (%dk total)\n", whoami, user,
- X size_to_k(file_ent->specs.st_size),
- X size_to_k(bytes_removed));
- X return 0;
- X }
- X else {
- X set_error(errno);
- X error(real);
- X return error_code;
- X }
- X}
- X
- X
- X
- X
- X
- X
- X
- X
- X
- Xtop_level()
- X{
- X if (interactive) {
- Xprintf("The above files, which have been marked for deletion, are about to be\n");
- Xprintf("expunged forever! You will be asked for confirmation before each file is\n");
- Xprintf("deleted. Do you wish to continue [return = no]? ");
- X }
- X else {
- Xprintf("The above files, which have been marked for deletion, are about to be\n");
- Xprintf("expunged forever! Make sure you don't need any of them before continuing.\n");
- Xprintf("Do you wish to continue [return = no]? ");
- X }
- X return (yes());
- X}
- X
- X
- X
- X
- X
- Xlist_files()
- X{
- X filerec *current;
- X char **strings;
- X int num;
- X int retval;
- X
- X strings = (char **) Malloc(sizeof(char *));
- X num = 0;
- X if (! strings) {
- X set_error(errno);
- X error("Malloc");
- X return error_code;
- X }
- X
- X printf("The following deleted files are going to be expunged: \n\n");
- X
- X current = get_root_tree();
- X if (retval = accumulate_names(current, &strings, &num)) {
- X error("accumulate_names");
- X return retval;
- X }
- X current = get_cwd_tree();
- X if (retval = accumulate_names(current, &strings, &num)) {
- X error("accumulate_names");
- X return retval;
- X }
- X if (retval = column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0,
- X 1, stdout)) {
- X error("column_array");
- X return retval;
- X }
- X
- X printf("\n");
- X return(0);
- X}
- X
- X
- X
- X
- X
- Xint get_the_files(name, num_found, found)
- Xchar *name;
- Xint *num_found;
- Xchar ***found;
- X{
- X int retval;
- X int options;
- X
- X options = FIND_DELETED | FIND_CONTENTS | RECURS_DELETED;
- X if (recursive)
- X options |= RECURS_FIND_DELETED;
- X if (f_mounts)
- X options |= FOLLW_MOUNTPOINTS;
- X if (f_links)
- X options |= FOLLW_LINKS;
- X
- X retval = find_matches(name, num_found, found, options);
- X if (retval) {
- X error("find_matches");
- X return retval;
- X }
- X
- X return 0;
- X}
- END_OF_FILE
- if test 11287 -ne `wc -c <'expunge.c'`; then
- echo shar: \"'expunge.c'\" unpacked with wrong size!
- fi
- # end of 'expunge.c'
- fi
- if test -f 'lsdel.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lsdel.c'\"
- else
- echo shar: Extracting \"'lsdel.c'\" \(7464 characters\)
- sed "s/^X//" >'lsdel.c' <<'END_OF_FILE'
- X/*
- X * $Source: /afs/athena.mit.edu/astaff/project/delete/src/RCS/lsdel.c,v $
- X * $Author: jik $
- X *
- X * This program is a replacement for rm. Instead of actually deleting
- X * files, it marks them for deletion by prefixing them with a ".#"
- X * prefix.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_lsdel_c[] = "$Header: /afs/athena.mit.edu/astaff/project/delete/src/RCS/lsdel.c,v 1.14 91/02/20 17:36:11 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/dir.h>
- X#include <sys/param.h>
- X#ifdef SYSV
- X#include <string.h>
- X#define index strchr
- X#define rindex strrchr
- X#else
- X#include <strings.h>
- X#endif /* SYSV */
- X#ifdef _AUX_SOURCE
- Xextern char *strcmp();
- X#endif
- X#include <errno.h>
- X#include <com_err.h>
- X#include "col.h"
- X#include "util.h"
- X#include "directories.h"
- X#include "pattern.h"
- X#include "lsdel.h"
- X#include "shell_regexp.h"
- X#include "mit-copyright.h"
- X#include "delete_errs.h"
- X#include "errors.h"
- X
- Xextern char *realloc();
- Xextern time_t current_time;
- Xextern int errno;
- X
- Xint byte_total = 0;
- Xint dirsonly, recursive, yield, f_links, f_mounts;
- Xtime_t timev;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X
- X whoami = lastpart(argv[0]);
- X
- X dirsonly = recursive = timev = yield = f_links = f_mounts = 0;
- X while ((arg = getopt(argc, argv, "drt:ysm")) != -1) {
- X switch (arg) {
- X case 'd':
- X dirsonly++;
- X break;
- X case 'r':
- X recursive++;
- X break;
- X case 't':
- X timev = atoi(optarg);
- X break;
- X case 'y':
- X yield++;
- X break;
- X case 's':
- X f_links++;
- X break;
- X case 'm':
- X f_mounts++;
- X break;
- X default:
- X usage();
- X exit(1);
- X }
- X }
- X if (optind == argc) {
- X char *cwd;
- X
- X cwd = ".";
- X
- X if (ls(&cwd, 1))
- X error("ls of .");
- X }
- X else if (ls(&argv[optind], argc - optind))
- X error ("ls");
- X
- X exit (error_occurred ? 1 : 0);
- X}
- X
- X
- X
- X
- X
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: %s [ options ] [ filename [ ...]]\n", whoami);
- X fprintf(stderr, "Options are:\n");
- X fprintf(stderr, " -d list directory names, not contents\n");
- X fprintf(stderr, " -r recursive\n");
- X fprintf(stderr, " -t n list n-day-or-older files only\n");
- X fprintf(stderr, " -y report total space taken up by files\n");
- X fprintf(stderr, " -s follow symbolic links to directories\n");
- X fprintf(stderr, " -m follow mount points\n");
- X}
- X
- X
- X
- X
- Xls(args, num)
- Xchar **args;
- Xint num;
- X{
- X char **found_files;
- X int num_found = 0, total = 0;
- X int status = 0;
- X int retval;
- X
- X initialize_del_error_table();
- X
- X if (retval = initialize_tree()) {
- X error("initialize_tree");
- X return retval;
- X }
- X
- X for ( ; num; num--) {
- X if (retval = get_the_files(args[num - 1], &num_found,
- X &found_files)) {
- X error(args[num - 1]);
- X status = retval;
- X continue;
- X }
- X
- X if (num_found) {
- X num_found = process_files(found_files, num_found);
- X if (num_found < 0) {
- X error("process_files");
- X status = error_code;
- X continue;
- X }
- X total += num_found;
- X }
- X else {
- X /* What we do at this point depends on exactly what the
- X * filename is. There are several possible conditions:
- X * 1. The filename has no wildcards in it, which means that
- X * if we couldn't find it, that means it doesn't
- X * exist. Print a not found error.
- X * 2. Filename is an existing directory, with no deleted
- X * files in it. Print nothing.
- X * 3. Filename doesn't exist, and there are wildcards in
- X * it. Print "no match".
- X * None of these are considered error conditions, so we
- X * don't set the error flag.
- X */
- X if (no_wildcards(args[num - 1])) {
- X if (! directory_exists(args[num - 1])) {
- X set_error(ENOENT);
- X error(args[num - 1]);
- X status = error_code;
- X continue;
- X }
- X }
- X else {
- X set_error(ENOMATCH);
- X error(args[num - 1]);
- X status = error_code;
- X continue;
- X }
- X }
- X }
- X if (total) {
- X if (list_files()) {
- X error("list_files");
- X return error_code;
- X }
- X }
- X if (yield)
- X printf("\nTotal space taken up by file%s: %dk\n",
- X (total == 1 ? "" : "s"), size_to_k(byte_total));
- X
- X return status;
- X}
- X
- X
- X
- X
- Xint get_the_files(name, number_found, found)
- Xchar *name;
- Xint *number_found;
- Xchar ***found;
- X{
- X int retval;
- X int options;
- X
- X options = FIND_DELETED | FIND_CONTENTS;
- X if (recursive)
- X options |= RECURS_FIND_DELETED;
- X if (! dirsonly)
- X options |= RECURS_DELETED;
- X if (f_mounts)
- X options |= FOLLW_MOUNTPOINTS;
- X if (f_links)
- X options |= FOLLW_LINKS;
- X
- X retval = find_matches(name, number_found, found, options);
- X if (retval) {
- X error("find_matches");
- X return retval;
- X }
- X
- X return 0;
- X}
- X
- X
- X
- X
- X
- X
- Xprocess_files(files, num)
- Xchar **files;
- Xint num;
- X{
- X int i, skipped = 0;
- X filerec *leaf;
- X
- X for (i = 0; i < num; i++) {
- X if (add_path_to_tree(files[i], &leaf)) {
- X error("add_path_to_tree");
- X return -1;
- X }
- X free(files[i]);
- X if (! timed_out(leaf, current_time, timev)) {
- X free_leaf(leaf);
- X skipped++;
- X continue;
- X }
- X byte_total += leaf->specs.st_size;
- X }
- X free((char *) files);
- X return(num-skipped);
- X}
- X
- X
- X
- X
- X
- Xlist_files()
- X{
- X filerec *current;
- X char **strings;
- X int num;
- X int retval;
- X
- X strings = (char **) Malloc((unsigned) sizeof(char *));
- X num = 0;
- X if (! strings) {
- X set_error(errno);
- X error("Malloc");
- X return error_code;
- X }
- X current = get_root_tree();
- X if (retval = accumulate_names(current, &strings, &num)) {
- X error("accumulate_names");
- X return retval;
- X }
- X current = get_cwd_tree();
- X if (retval = accumulate_names(current, &strings, &num)) {
- X error("accumulate_names");
- X return retval;
- X }
- X
- X if (retval = sort_files(strings, num)) {
- X error("sort_files");
- X return retval;
- X }
- X
- X if (retval = unique(&strings, &num)) {
- X error("unique");
- X return retval;
- X }
- X
- X if (retval = column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0,
- X 1, stdout)) {
- X error("column_array");
- X return retval;
- X }
- X
- X for ( ; num; num--)
- X free(strings[num - 1]);
- X free((char *) strings);
- X return 0;
- X}
- X
- X
- Xint sort_files(data, num_data)
- Xchar **data;
- Xint num_data;
- X{
- X qsort((char *) data, num_data, sizeof(char *), strcmp);
- X
- X return 0;
- X}
- X
- X
- Xint unique(the_files, number)
- Xchar ***the_files;
- Xint *number;
- X{
- X int i, last;
- X int offset;
- X char **files;
- X
- X files = *the_files;
- X for (last = 0, i = 1; i < *number; i++) {
- X if (! strcmp(files[last], files[i])) {
- X free (files[i]);
- X free (files[i]);
- X files[i] = (char *) NULL;
- X }
- X else
- X last = i;
- X }
- X
- X for (offset = 0, i = 0; i + offset < *number; i++) {
- X if (! files[i])
- X offset++;
- X if (i + offset < *number)
- X files[i] = files[i + offset];
- X }
- X *number -= offset;
- X files = (char **) realloc((char *) files,
- X (unsigned) (sizeof(char *) * *number));
- X if ((*number != 0) && (! files)) {
- X set_error(errno);
- X error("realloc");
- X return errno;
- X }
- X
- X *the_files = files;
- X return 0;
- X}
- END_OF_FILE
- if test 7464 -ne `wc -c <'lsdel.c'`; then
- echo shar: \"'lsdel.c'\" unpacked with wrong size!
- fi
- # end of 'lsdel.c'
- fi
- if test -f 'undelete.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'undelete.c'\"
- else
- echo shar: Extracting \"'undelete.c'\" \(12715 characters\)
- sed "s/^X//" >'undelete.c' <<'END_OF_FILE'
- X/*
- X * $Source: /afs/athena.mit.edu/astaff/project/delete/src/RCS/undelete.c,v $
- X * $Author: jik $
- X *
- X * This program is part of a package including delete, undelete,
- X * lsdel, expunge and purge. The software suite is meant as a
- X * replacement for rm which allows for file recovery.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_undelete_c[] = "$Header: /afs/athena.mit.edu/astaff/project/delete/src/RCS/undelete.c,v 1.22 91/02/20 17:27:38 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/dir.h>
- X#include <sys/param.h>
- X#ifdef SYSV
- X#include <string.h>
- X#define index strchr
- X#define rindex strrchr
- X#else
- X#include <strings.h>
- X#endif /* SYSV */
- X#include <com_err.h>
- X#include <errno.h>
- X#include "delete_errs.h"
- X#include "pattern.h"
- X#include "util.h"
- X#include "directories.h"
- X#include "undelete.h"
- X#include "shell_regexp.h"
- X#include "mit-copyright.h"
- X#include "errors.h"
- X
- Xextern char *realloc();
- Xextern int errno;
- X
- Xint interactive, recursive, verbose, directoriesonly, noop, force;
- X
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X int retval;
- X
- X initialize_del_error_table();
- X
- X whoami = lastpart(argv[0]);
- X interactive = recursive = verbose = directoriesonly = noop = force = 0;
- X
- X while ((arg = getopt(argc, argv, "firvnR")) != -1) {
- X switch (arg) {
- X case 'f':
- X force++;
- X break;
- X case 'i':
- X interactive++;
- X break;
- X case 'r':
- X recursive++;
- X if (directoriesonly) {
- X fprintf(stderr, "%s: -r and -R and mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(1);
- X }
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'n':
- X noop++;
- X break;
- X case 'R':
- X directoriesonly++;
- X if (recursive) {
- X fprintf(stderr, "%s: -r and -R are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(1);
- X }
- X break;
- X default:
- X usage();
- X exit(1);
- X }
- X }
- X
- X report_errors = ! force;
- X
- X if (optind == argc) {
- X if (interactive_mode())
- X error("interactive_mode");
- X }
- X else while (optind < argc) {
- X retval = undelete(argv[optind]);
- X if (retval)
- X error(argv[optind]);
- X optind++;
- X }
- X exit(((! force) && error_occurred) ? 1 : 0);
- X}
- X
- X
- X
- Xinteractive_mode()
- X{
- X char buf[MAXPATHLEN];
- X char *ptr;
- X int status = 0;
- X int retval;
- X
- X if (verbose) {
- X printf("Enter the files to be undeleted, one file per line.\n");
- X printf("Hit <RETURN> on a line by itself to exit.\n\n");
- X }
- X do {
- X printf("%s: ", whoami);
- X ptr = fgets(buf, MAXPATHLEN, stdin);
- X if (! ptr) {
- X printf("\n");
- X return status;
- X }
- X ptr = index(buf, '\n'); /* fgets breakage */
- X if (ptr)
- X *ptr = '\0';
- X if (! *buf)
- X return status;
- X retval = undelete(buf);
- X if (retval) {
- X error(buf);
- X status = retval;
- X }
- X } while (*buf);
- X return status;
- X}
- X
- X
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: %s [ options ] [filename ...]\n", whoami);
- X fprintf(stderr, "Options are:\n");
- X fprintf(stderr, " -r recursive\n");
- X fprintf(stderr, " -i interactive\n");
- X fprintf(stderr, " -f force\n");
- X fprintf(stderr, " -v verbose\n");
- X fprintf(stderr, " -n noop\n");
- X fprintf(stderr, " -R directories only (i.e. no recursion)\n");
- X fprintf(stderr, " -- end options and start filenames\n");
- X fprintf(stderr, "-r and -D are mutually exclusive\n");
- X}
- X
- Xundelete(name)
- Xchar *name;
- X{
- X char **found_files;
- X int num_found;
- X int status = 0;
- X filerec *current;
- X int retval;
- X
- X if (retval = get_the_files(name, &num_found, &found_files)) {
- X error(name);
- X return retval;
- X }
- X
- X if (num_found) {
- X if (retval = process_files(found_files, num_found)) {
- X error(name);
- X return retval;
- X }
- X if (*name == '/')
- X current = get_root_tree();
- X else
- X current = get_cwd_tree();
- X
- X status = recurs_and_undelete(current);
- X if (status) {
- X error(name);
- X return status;
- X }
- X }
- X else {
- X if (no_wildcards(name)) {
- X set_error(ENOENT)
- X }
- X else
- X set_error(ENOMATCH);
- X error(name);
- X return error_code;
- X }
- X
- X return status;
- X}
- X
- X
- X
- X
- X
- Xint recurs_and_undelete(leaf)
- Xfilerec *leaf;
- X{
- X int status = 0;
- X int retval;
- X
- X if (leaf->specified) {
- X retval = do_undelete(leaf);
- X if (retval) {
- X error("do_undelete");
- X status = retval;
- X }
- X }
- X
- X if (! status) { /* recurse only if if top-level undelete */
- X /* succeeded or was not requested */
- X if (leaf->dirs) {
- X retval = recurs_and_undelete(leaf->dirs);
- X if (retval) {
- X error("recurs_and_undelete");
- X status = retval;
- X }
- X }
- X
- X if (leaf->files) {
- X retval = recurs_and_undelete(leaf->files);
- X if (retval) {
- X error("recurs_and_undelete");
- X status = retval;
- X }
- X }
- X }
- X
- X if (leaf->next) {
- X retval = recurs_and_undelete(leaf->next);
- X if (retval) {
- X error("recurs_and_undelete");
- X status = retval;
- X }
- X }
- X
- X free_leaf(leaf);
- X
- X return status;
- X}
- X
- X
- X
- X
- X
- X
- Xint process_files(files, num)
- Xchar **files;
- Xint num;
- X{
- X int i;
- X listrec *filelist;
- X struct filrec *not_needed;
- X int retval;
- X
- X filelist = (listrec *) Malloc((unsigned) (sizeof(listrec) * num));
- X if (! filelist) {
- X set_error(errno);
- X error("process_files");
- X return error_code;
- X }
- X
- X for (i = 0; i < num; i++) {
- X filelist[i].real_name = Malloc((unsigned) (strlen(files[i]) + 1));
- X if (! filelist[i].real_name) {
- X set_error(errno);
- X error("process_files");
- X return error_code;
- X }
- X (void) strcpy(filelist[i].real_name, files[i]);
- X filelist[i].user_name = Malloc((unsigned) (strlen(files[i]) + 1));
- X if (! filelist[i].user_name) {
- X set_error(errno);
- X error("process_files");
- X return error_code;
- X }
- X (void) convert_to_user_name(files[i], filelist[i].user_name);
- X free(files[i]);
- X }
- X free((char *) files);
- X
- X if (retval = sort_files(filelist, num)) {
- X error("sort_files");
- X return retval;
- X }
- X if (retval = unique(&filelist, &num)) {
- X error("unique");
- X return retval;
- X }
- X if (retval = initialize_tree()) {
- X error("initialize_tree");
- X return retval;
- X }
- X
- X for (i = 0; i < num; i++) {
- X if (retval = add_path_to_tree(filelist[i].real_name, ¬_needed)) {
- X error("add_path_to_tree");
- X return retval;
- X }
- X else {
- X free(filelist[i].real_name);
- X free(filelist[i].user_name);
- X }
- X }
- X free((char *) filelist);
- X return 0;
- X}
- X
- X
- X
- X
- X
- X
- X
- X
- Xdo_undelete(file_ent)
- Xfilerec *file_ent;
- X{
- X struct stat stat_buf;
- X char user_name[MAXPATHLEN], real_name[MAXPATHLEN];
- X int retval;
- X
- X if (retval = get_leaf_path(file_ent, real_name)) {
- X if (! force)
- X fprintf(stderr, "%s: %s: %s\n", whoami, "get_leaf_path",
- X error_message(retval));
- X return retval;
- X }
- X
- X (void) convert_to_user_name(real_name, user_name);
- X
- X if (interactive) {
- X if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
- X printf("%s: Undelete directory %s? ", whoami, user_name);
- X else
- X printf("%s: Undelete %s? ", whoami, user_name);
- X if (! yes()) {
- X set_status(UNDEL_NOT_UNDELETED);
- X return error_code;
- X }
- X }
- X if (! lstat(user_name, &stat_buf)) if (! force) {
- X printf("%s: An undeleted %s already exists.\n", whoami, user_name);
- X printf("Do you wish to continue with the undelete and overwrite that version? ");
- X if (! yes()) {
- X set_status(UNDEL_NOT_UNDELETED);
- X return error_code;
- X }
- X if (! noop) if (retval = unlink_completely(user_name)) {
- X error(user_name);
- X return retval;
- X }
- X }
- X if (noop) {
- X printf("%s: %s would be undeleted\n", whoami, user_name);
- X return 0;
- X }
- X
- X if (retval = do_file_rename(real_name, user_name)) {
- X error("do_file_rename");
- X return retval;
- X }
- X else {
- X if (verbose)
- X printf("%s: %s undeleted\n", whoami, user_name);
- X return 0;
- X }
- X}
- X
- X
- X
- X
- Xdo_file_rename(real_name, user_name)
- Xchar *real_name, *user_name;
- X{
- X char *ptr;
- X int retval;
- X char error_buf[MAXPATHLEN+MAXPATHLEN+14];
- X char old_name[MAXPATHLEN], new_name[MAXPATHLEN];
- X char buf[MAXPATHLEN];
- X
- X (void) strcpy(old_name, real_name);
- X (void) strcpy(new_name, real_name);
- X
- X while (ptr = strrindex(new_name, ".#")) {
- X (void) convert_to_user_name(ptr, ptr);
- X (void) strcpy(ptr, firstpart(ptr, buf));
- X (void) strcpy(&old_name[ptr - new_name],
- X firstpart(&old_name[ptr - new_name], buf));
- X if (rename(old_name, new_name)) {
- X set_error(errno);
- X (void) sprintf(error_buf, "renaming %s to %s",
- X old_name, new_name);
- X error(error_buf);
- X return error_code;
- X }
- X if (ptr > new_name) {
- X *--ptr = '\0';
- X old_name[ptr - new_name] = '\0';
- X }
- X }
- X if (retval = change_path(real_name, user_name)) {
- X error("change_path");
- X return retval;
- X }
- X
- X return 0;
- X}
- X
- X
- X
- X
- X
- X
- Xfilecmp(file1, file2)
- Xlistrec *file1, *file2;
- X{
- X return(strcmp(file1->user_name, file2->user_name));
- X}
- X
- X
- X
- Xint sort_files(data, num_data)
- Xlistrec *data;
- Xint num_data;
- X{
- X qsort((char *) data, num_data, sizeof(listrec), filecmp);
- X
- X return 0;
- X}
- X
- X
- X
- X
- X
- Xint unique(the_files, number)
- Xlistrec **the_files;
- Xint *number;
- X{
- X int i, last;
- X int offset;
- X listrec *files;
- X
- X files = *the_files;
- X for (last = 0, i = 1; i < *number; i++) {
- X if (! strcmp(files[last].user_name, files[i].user_name)) {
- X int better;
- X
- X better = choose_better(files[last].real_name,
- X files[i].real_name);
- X if (better == 1) { /* the first one is better */
- X free (files[i].real_name);
- X free (files[i].user_name);
- X files[i].real_name = (char *) NULL;
- X }
- X else {
- X free (files[last].real_name);
- X free (files[last].user_name);
- X files[last].real_name = (char *) NULL;
- X last = i;
- X }
- X }
- X else
- X last = i;
- X }
- X
- X for (offset = 0, i = 0; i + offset < *number; i++) {
- X if (! files[i].real_name)
- X offset++;
- X if (i + offset < *number)
- X files[i] = files[i + offset];
- X }
- X *number -= offset;
- X files = (listrec *) realloc((char *) files,
- X (unsigned) (sizeof(listrec) * *number));
- X if (! files) {
- X set_error(errno);
- X error("realloc");
- X return errno;
- X }
- X
- X *the_files = files;
- X return 0;
- X}
- X
- X
- X
- X
- Xchoose_better(str1, str2)
- Xchar *str1, *str2;
- X{
- X char *pos1, *pos2;
- X
- X pos1 = strindex(str1, ".#");
- X pos2 = strindex(str2, ".#");
- X while (pos1 && pos2) {
- X if (pos1 - str1 < pos2 - str2)
- X return(2);
- X else if (pos2 - str2 < pos1 - str1)
- X return(1);
- X pos1 = strindex(pos1 + 1, ".#");
- X pos2 = strindex(pos2 + 1, ".#");
- X }
- X if (! pos1)
- X return(1);
- X else
- X return(2);
- X}
- X
- X
- X
- X
- X
- Xunlink_completely(filename)
- Xchar *filename;
- X{
- X char buf[MAXPATHLEN];
- X struct stat stat_buf;
- X DIR *dirp;
- X struct direct *dp;
- X int retval;
- X int status = 0;
- X
- X if (lstat(filename, &stat_buf)) {
- X set_error(errno);
- X error(filename);
- X return error_code;
- X }
- X
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X dirp = Opendir(filename);
- X if (! dirp) {
- X set_error(errno);
- X error(filename);
- X return error_code;
- X }
- X
- X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X if (is_dotfile(dp->d_name))
- X continue;
- X (void) strcpy(buf, append(filename, dp->d_name));
- X if (retval = unlink_completely(buf)) {
- X error(buf);
- X status = retval;
- X }
- X }
- X closedir(dirp);
- X if (retval = rmdir(filename)) {
- X set_error(errno);
- X error(filename);
- X return error_code;
- X }
- X }
- X else if (retval = unlink(filename)) {
- X set_error(errno);
- X error(filename);
- X return error_code;
- X }
- X
- X return status;
- X}
- X
- X
- X
- X
- Xint get_the_files(name, num_found, found)
- Xchar *name;
- Xint *num_found;
- Xchar ***found;
- X{
- X int retval;
- X int options;
- X
- X options = FIND_DELETED;
- X if (recursive)
- X options |= RECURS_DELETED;
- X if (! directoriesonly)
- X options |= FIND_CONTENTS;
- X
- X retval = find_matches(name, num_found, found, options);
- X if (retval) {
- X error("find_matches");
- X return retval;
- X }
- X
- X return 0;
- X}
- END_OF_FILE
- if test 12715 -ne `wc -c <'undelete.c'`; then
- echo shar: \"'undelete.c'\" unpacked with wrong size!
- fi
- # end of 'undelete.c'
- fi
- if test -f 'util.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'util.c'\"
- else
- echo shar: Extracting \"'util.c'\" \(8062 characters\)
- sed "s/^X//" >'util.c' <<'END_OF_FILE'
- X/*
- X * $Source: /afs/athena.mit.edu/astaff/project/delete/src/RCS/util.c,v $
- X * $Author: jik $
- X *
- X * This program is a replacement for rm. Instead of actually deleting
- X * files, it marks them for deletion by prefixing them with a ".#"
- X * prefix.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_util_c[] = "$Header: /afs/athena.mit.edu/astaff/project/delete/src/RCS/util.c,v 1.21 91/02/20 17:28:11 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#ifdef SYSV /* SYSV doesn't define uid_t */
- Xtypedef unsigned short uid_t;
- X#endif
- X#include <sys/dir.h>
- X#ifdef SYSV
- X#include <string.h>
- X#define index strchr
- X#define rindex strrchr
- X#else
- X#include <strings.h>
- X#endif /* SYSV */
- X#include <pwd.h>
- X#include <errno.h>
- X#ifdef AFS_MOUNTPOINTS
- X#include <sys/ioctl.h>
- X#include <afs/param.h>
- X#include <afs/vice.h>
- X#include <afs/venus.h>
- X#endif
- X#include "delete_errs.h"
- X#include "util.h"
- X#include "directories.h"
- X#include "mit-copyright.h"
- X#include "errors.h"
- X
- Xextern char *getenv();
- Xextern uid_t getuid();
- Xextern int errno;
- X
- Xchar *convert_to_user_name(real_name, user_name)
- Xchar real_name[];
- Xchar user_name[]; /* RETURN */
- X{
- X char *ptr, *q;
- X
- X (void) strcpy(user_name, real_name);
- X while (ptr = strrindex(user_name, ".#")) {
- X for (q = ptr; *(q + 2); q++)
- X *q = *(q + 2);
- X *q = '\0';
- X }
- X return (user_name);
- X}
- X
- X
- X
- X
- X
- Xchar *strindex(str, sub_str)
- Xchar *str, *sub_str;
- X{
- X char *ptr = str;
- X while (ptr = index(ptr, *sub_str)) {
- X if (! strncmp(ptr, sub_str, strlen(sub_str)))
- X return(ptr);
- X ptr++;
- X }
- X return ((char *) NULL);
- X}
- X
- X
- X
- Xchar *strrindex(str, sub_str)
- Xchar *str, *sub_str;
- X{
- X char *ptr;
- X
- X if (strlen(str))
- X ptr = &str[strlen(str) - 1];
- X else
- X return((char *) NULL);
- X while ((*ptr != *sub_str) && (ptr != str)) ptr--;
- X while (ptr != str) {
- X if (! strncmp(ptr, sub_str, strlen(sub_str)))
- X return(ptr);
- X ptr--;
- X while ((*ptr != *sub_str) && (ptr != str)) ptr--;
- X }
- X if (! strncmp(ptr, sub_str, strlen(sub_str)))
- X return(str);
- X else
- X return ((char *) NULL);
- X}
- X
- X
- X/*
- X * NOTE: Append uses a static array, so its return value must be
- X * copied immediately.
- X */
- Xchar *append(filepath, filename)
- Xchar *filepath, *filename;
- X{
- X static char buf[MAXPATHLEN];
- X
- X (void) strcpy(buf, filepath);
- X if ((! *filename) || (! *filepath)) {
- X (void) strcpy(buf, filename);
- X return(buf);
- X }
- X if (buf[strlen(buf) - 1] == '/')
- X buf[strlen(buf) - 1] = '\0';
- X if (strlen(buf) + strlen(filename) + 2 > MAXPATHLEN) {
- X set_error(ENAMETOOLONG);
- X strncat(buf, "/", MAXPATHLEN - strlen(buf) - 1);
- X strncat(buf, filename, MAXPATHLEN - strlen(buf) - 1);
- X error(buf);
- X *buf = '\0';
- X return buf;
- X }
- X (void) strcat(buf, "/");
- X (void) strcat(buf, filename);
- X return buf;
- X}
- X
- X
- X
- X
- Xyes() {
- X char buf[BUFSIZ];
- X char *val;
- X
- X val = fgets(buf, BUFSIZ, stdin);
- X if (! val) {
- X printf("\n");
- X exit(1);
- X }
- X if (! index(buf, '\n')) do
- X (void) fgets(buf + 1, BUFSIZ - 1, stdin);
- X while (! index(buf + 1, '\n'));
- X return(*buf == 'y');
- X}
- X
- X
- X
- X
- Xchar *lastpart(filename)
- Xchar *filename;
- X{
- X char *part;
- X
- X part = rindex(filename, '/');
- X
- X if (! part)
- X part = filename;
- X else if (part == filename)
- X part++;
- X else if (part - filename + 1 == strlen(filename)) {
- X part = rindex(--part, '/');
- X if (! part)
- X part = filename;
- X else
- X part++;
- X }
- X else
- X part++;
- X
- X return(part);
- X}
- X
- X
- X
- X
- Xchar *firstpart(filename, rest)
- Xchar *filename;
- Xchar *rest; /* RETURN */
- X{
- X char *part;
- X static char buf[MAXPATHLEN];
- X
- X (void) strcpy(buf, filename);
- X part = index(buf, '/');
- X if (! part) {
- X *rest = '\0';
- X return(buf);
- X }
- X (void) strcpy(rest, part + 1);
- X *part = '\0';
- X return(buf);
- X}
- X
- X
- X
- X
- X
- Xget_home(buf)
- Xchar *buf;
- X{
- X char *user;
- X struct passwd *psw;
- X
- X (void) strcpy(buf, getenv("HOME"));
- X
- X if (*buf)
- X return(0);
- X
- X user = getenv("USER");
- X psw = getpwnam(user);
- X
- X if (psw) {
- X (void) strcpy(buf, psw->pw_dir);
- X return(0);
- X }
- X
- X psw = getpwuid((int) getuid());
- X
- X if (psw) {
- X (void) strcpy(buf, psw->pw_dir);
- X return(0);
- X }
- X
- X set_error(NO_HOME_DIR);
- X error("get_home");
- X return error_code;
- X}
- X
- X
- X
- X
- Xtimed_out(file_ent, current_time, min_days)
- Xfilerec *file_ent;
- Xtime_t current_time, min_days;
- X{
- X if ((current_time - file_ent->specs.st_ctime) / 86400 >= min_days)
- X return(1);
- X else
- X return(0);
- X}
- X
- X
- X
- Xint directory_exists(dirname)
- Xchar *dirname;
- X{
- X struct stat stat_buf;
- X
- X if (stat(dirname, &stat_buf))
- X return(0);
- X else if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
- X return(1);
- X else
- X return(0);
- X}
- X
- X
- X
- Xis_link(name, oldbuf)
- Xchar *name;
- Xstruct stat *oldbuf;
- X{
- X#ifdef S_IFLNK
- X struct stat statbuf;
- X
- X if (oldbuf)
- X statbuf = *oldbuf;
- X else if (lstat(name, &statbuf) < 0) {
- X set_error(errno);
- X error("is_link");
- X return(0);
- X }
- X
- X if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
- X return 1;
- X else
- X#endif
- X return 0;
- X}
- X
- X
- X
- X/*
- X * This is one of the few procedures that is allowed to break the
- X * rule of always returning an error value if an error occurs. That's
- X * because it's stupid to expect a boolean function to do that, and
- X * because defaulting to not being a mountpoint if there is an error
- X * is a reasonable thing to do.
- X */
- X/*
- X * The second parameter is optional -- if it is non-NULL, it is
- X * presumed to be a stat structure for the file being passed in.
- X */
- Xint is_mountpoint(name, oldbuf)
- Xchar *name;
- Xstruct stat *oldbuf;
- X{
- X struct stat statbuf;
- X dev_t device;
- X char buf[MAXPATHLEN];
- X#ifdef AFS_MOUNTPOINTS
- X struct ViceIoctl blob;
- X char retbuf[MAXPATHLEN];
- X int retval;
- X char *shortname;
- X#endif
- X
- X /* First way to check for a mount point -- if the device number */
- X /* of name is different from the device number of name/.. */
- X if (oldbuf)
- X statbuf = *oldbuf;
- X else if (lstat(name, &statbuf) < 0) {
- X set_error(errno);
- X error(name);
- X return 0;
- X }
- X
- X device = statbuf.st_dev;
- X
- X if (strlen(name) + 4 /* length of "/.." + a NULL */ > MAXPATHLEN) {
- X set_error(ENAMETOOLONG);
- X error(name);
- X return 0;
- X }
- X
- X strcpy(buf, name);
- X strcat(buf, "/..");
- X if (lstat(buf, &statbuf) < 0) {
- X set_error(errno);
- X error(name);
- X return 0;
- X }
- X
- X if (statbuf.st_dev != device)
- X return 1;
- X
- X#ifdef AFS_MOUNTPOINTS
- X /* Check for AFS mountpoint using the AFS pioctl call. */
- X if ((shortname = lastpart(name)) == name) {
- X strcpy(buf, ".");
- X blob.in = name;
- X blob.in_size = strlen(name) + 1;
- X blob.out = retbuf;
- X blob.out_size = MAXPATHLEN;
- X bzero(retbuf, MAXPATHLEN);
- X }
- X else {
- X strncpy(buf, name, shortname - name - 1);
- X buf[shortname - name - 1] = '\0';
- X if (*buf == '\0')
- X strcpy(buf, "/");
- X blob.in = shortname;
- X blob.in_size = strlen(shortname) + 1;
- X blob.out = retbuf;
- X blob.out_size = MAXPATHLEN;
- X bzero(retbuf, MAXPATHLEN);
- X }
- X
- X retval = pioctl(buf, VIOC_AFS_STAT_MT_PT, &blob, 0);
- X
- X if (retval == 0) {
- X#ifdef DEBUG
- X printf("%s is an AFS mountpoint, is_mountpoint returning true.\n",
- X name);
- X#endif
- X return 1;
- X }
- X else {
- X if (errno != EINVAL) {
- X set_error(errno);
- X error(name);
- X }
- X }
- X#endif /* AFS_MOUNTPOINTS */
- X
- X return 0;
- X}
- X
- X#ifdef MALLOC_DEBUG
- Xchar *Malloc(size)
- Xunsigned size;
- X{
- X extern char *malloc();
- X
- X static int count = 0;
- X char buf[10];
- X
- X count++;
- X
- X fprintf(stderr, "This is call number %d to Malloc, for %u bytes.\n",
- X count, size);
- X fprintf(stdout, "Shall I return NULL for this malloc? ");
- X fgets(buf, 10, stdin);
- X if ((*buf == 'y') || (*buf == 'Y')) {
- X errno = ENOMEM;
- X return ((char *) NULL);
- X }
- X else
- X return (malloc(size));
- X}
- X#endif
- X
- X
- END_OF_FILE
- if test 8062 -ne `wc -c <'util.c'`; then
- echo shar: \"'util.c'\" unpacked with wrong size!
- fi
- # end of 'util.c'
- fi
- echo shar: End of archive 2 \(of 4\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-